package cn.rjzjh.tapestry.tams.pages.sys;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.util.TextStreamResponse;
import org.hibernate.Session;
import org.w3c.dom.Document;

import cn.rjzjh.commons.util.apiext.JSONUtil;
import cn.rjzjh.commons.util.apiext.XmlUtil;
import cn.rjzjh.commons.util.assistbean.EasyUINode;
import cn.rjzjh.commons.util.assistbean.NodeSax;
import cn.rjzjh.commons.util.callback.IConvertValue;
import cn.rjzjh.commons.util.web.EasyUiAssist;
import cn.rjzjh.commons.util.web.OperateResult;
import cn.rjzjh.tapestry.busi.SpringInit;
import cn.rjzjh.tapestry.busi.model.ca.CaResType;
import cn.rjzjh.tapestry.busi.model.ca.CaResource;
import cn.rjzjh.tapestry.busi.service.IMenuService;
import cn.rjzjh.tapestry.component.tools.TapestryAssist;
import cn.rjzjh.tapestry.tams.base.ParentPage;
import cn.rjzjh.tapestry.tams.services.base.IHbService;

@Import(stack = "easyuistack")
public class ResManager extends ParentPage {
	@Inject
	private IMenuService menuService;
	@Inject
	private IHbService hbService;

	@Inject
	private Session session;

	@Property
	private CaResource res;

	public TextStreamResponse onQueryMenu() throws Exception {
		List<EasyUINode> roots = menuService.findAllModuleMenu(I18NConvert,
				true);
		String retstr = EasyUiAssist.getTreeFromList(roots);
		return retStream(retstr);
	}

	public TextStreamResponse onListResType() {
		List<CaResType> resList = menuService.findCanEditResType();
		Map<String, IConvertValue> convMap = new HashMap<String, IConvertValue>();
		convMap.put("resTypeCode1", I18NConvert);
		String retstr = JSONUtil.getJsonForListAlias(resList,
				new String[] { "resTypeCode,resTypeCode1" }, convMap);
		return retStream(retstr);
	}

	@CommitAfter
	public TextStreamResponse onSaveRes() {
		JSONObject params = TapestryAssist.packParams(request);
		String id = params.getString("id");
		String parentId = params.getString("parentId");
		String icon = params.getString("icon");
		String resLevel = params.getString("resLevel");
		String caResType = params.getString("caResType");

		String showOrder = params.getString("showOrder");
		String resCode = params.getString("resCode");
		String resName = params.getString("resName");
		String resValue = params.getString("resValue");
		String canEdit = params.getString("canEdit");
		String remark = params.getString("remark");

		CaResource rs = new CaResource();
		if (StringUtils.isNotBlank(id)) {
			rs.setId(Integer.parseInt(id));
		}

		rs.setResCode(resCode);
		rs.setResName(resName);
		rs.setResValue(resValue);
		rs.setCaResType(new CaResType(Integer.parseInt(caResType)));
		rs.setIcon(icon);
		rs.setResLevel(Integer.parseInt(resLevel));
		rs.setCanEdit(canEdit);
		CaResource parent = "-1".equals(parentId) ? null : new CaResource(
				Integer.parseInt(parentId));
		rs.setCaResource(parent);
		rs.setShowOrder(Integer.parseInt(showOrder));
		rs.setRemark(remark);
		rs = (CaResource) session.merge(rs);
		OperateResult res = new OperateResult(1);
		JSONObject retobj = res.getJsonObj();
		retobj.put("id", rs.getId());

		JSONObject attributes = new JSONObject("resCode", resCode, "resName",
				resName, "resValue", resValue, "canEdit", canEdit, "remark",
				remark);
		retobj.put("attributes", attributes);
		retobj.put("index", Integer.parseInt(showOrder));
		retobj.put("text", I18NConvert.getStr(resName));
		return retStream(retobj.toString());
	}

	/****
	 * 删除Res
	 *
	 * @return
	 */
	@CommitAfter
	public TextStreamResponse onDelRes() {
		String id = request.getParameter("id");
		hbService.delById(CaResource.class, Integer.parseInt(id));
		OperateResult ret = new OperateResult(1);
		return retStream(ret.getJsonMsg(null));
	}

	/**
	 * 更新菜单列表，当前的方案是：扫描page目录下的TML文件及目录结构
	 *
	 * @return
	 */
	@CommitAfter
	public TextStreamResponse onSyncRes() {
		List<Integer> mods = hbService.getQuery(
				"select id from CaResource where caResource.id=1").list();

		OperateResult ret = new OperateResult(0);
		try {
			ret.setResult(1);
			Collection<File> files = FileUtils.listFiles(new File(
					SpringInit.pagePath), fileFilter, dirFilter);

			CaResType resType = (CaResType) session.get(CaResType.class, 3);// 只同步菜单类型的资源
			final List<CaResource> hasResList = new ArrayList<CaResource>();
			for (File file : files) {
				CaResource res = new CaResource();
				res.setCaResType(resType);

				String path = file.getPath();
				int beginIndex = path.indexOf("pages" + File.separator);
				int endIndex = path.indexOf(".tml");
				path = path.substring(beginIndex + 5, endIndex);
				res.setResValue(path.replaceAll("\\" + File.separator, "/"));// 资源值
				res.setResCode(path.replaceAll("\\" + File.separator, "_"));
				String fileContext = FileUtils.readFileToString(file, "utf-8");
				int beginTitle = fileContext.indexOf("<title");
				int endTitle = fileContext.indexOf("</title>");

				boolean isMenu = false;
				String value = "";
				int module = -1;
				if (beginTitle >= 0 && endTitle > beginTitle) {
					try {
						Document doc = XmlUtil.parserDocment(fileContext
								.substring(beginTitle, endTitle + 8));
						if (doc != null && doc.getFirstChild() != null
								&& doc.getFirstChild().getFirstChild() != null) {
							value = doc.getFirstChild().getFirstChild()
									.getNodeValue();
							String isMenuStr = findAttrByName(doc, "isMenu");
							isMenu = Boolean.parseBoolean(isMenuStr);

							String moduleStr = findAttrByName(doc, "module");// 它可以没有
							try {
								module = Integer.parseInt(moduleStr);
								if (!mods.contains(module)) {// 页面设置的模块不在数据库中
									module = -1;
								}
							} catch (Exception e) {
							}

						}
					} catch (Exception e) {
					}
				}
				if (!isMenu) {// 是菜单
					continue;
				}

				if (module > 0) {
					res.setCaResource(new CaResource(module));
				}

				value = value.replace("$", "").replace("{", "")
						.replace("}", "").replace("message:", "");
				res.setResName(StringUtils.isEmpty(value) ? file.getName()
						: value);// 资源名称，国际化的key值,如果没拿到key值，就用文件名代替
				hasResList.add(res);
			}
			final List<CaResource> dbResList = menuService.findSyncRes();// 查找数据库已有的菜单
			// 数据库中有的，但已不存在此页面的，需要删除
			List<CaResource> deleteList = (List<CaResource>) CollectionUtils
					.select(dbResList, new Predicate() {
						@Override
						public boolean evaluate(Object object) {
							return !hasResList.contains(object);
						}
					});

			for (CaResource ca_Resource : deleteList) {
				session.delete(ca_Resource);
			}

			// dbResList 剩余的集合、更新
			List<CaResource> updateList = (List<CaResource>) CollectionUtils
					.select(dbResList, new Predicate() {
						@Override
						public boolean evaluate(Object object) {
							CaResource tempobj = (CaResource) object;
							return hasResList.contains(object)
									&& "yes".equals(tempobj.getCanEdit());
						}
					});
			for (CaResource ca_Resource : updateList) {
				CaResource updateObj = hasResList.get(hasResList
						.indexOf(ca_Resource));
				ca_Resource.setResCode(updateObj.getResCode());
				ca_Resource.setResName(updateObj.getResName());
				ca_Resource.setResValue(updateObj.getResValue());
				ca_Resource.setRemark("程序自动更新");
			}
			for (CaResource caResource : updateList) {
				session.update(caResource);
			}

			// 数据库没有的，但已存在的、需添加
			List<CaResource> addList = (List<CaResource>) CollectionUtils
					.select(hasResList, new Predicate() {
						@Override
						public boolean evaluate(Object object) {
							return !dbResList.contains(object);
						}
					});

			for (CaResource caResource : addList) {
				int secIndex = caResource.getResValue().indexOf("/", 1);
				int threeIndex = caResource.getResValue().indexOf("/",
						secIndex + 1);
				caResource.setIcon("icon-user");
				caResource.setCanEdit("yes");
				caResource.setRemark("系统自动同步");
				// caResource.setCaResource(defaulModel);
				caResource.setResLevel(2);
				session.save(caResource);
			}
		} catch (Exception e) {
			ret.setMessage(LK("tip.sys.error.sync") + e.getMessage());
		}
		return new TextStreamResponse("text/html", ret.getJsonMsg(I18NConvert));
	}

	private String findAttrByName(Document doc, String nodeName) {
		String retstr = null;
		try {
			retstr = doc.getFirstChild().getAttributes().getNamedItem(nodeName)
					.getNodeValue();
		} catch (Exception e) {
		}
		return retstr;
	}

	IOFileFilter fileFilter = new IOFileFilter() {
		@Override
		public boolean accept(File dir, String name) {
			if (name.endsWith(".tml")) {
				return true;
			} else {
				return false;
			}
		}

		@Override
		public boolean accept(File file) {
			String name = file.getName();
			if (name.endsWith(".tml")) {
				return true;
			} else {
				return false;
			}
		}
	};

	IOFileFilter dirFilter = new IOFileFilter() {
		@Override
		public boolean accept(File dir, String name) {
			if (name.endsWith(".tml")) {
				return true;
			} else {
				return false;
			}
		}

		@Override
		public boolean accept(File file) {
			return true;
		}
	};

}
